/*
 * @Author       : wfl
 * @LastEditors: qiye
 * @description  :
 * @updateInfo   :
 * @Date         : 2023-02-24 16:08:34
 * @LastEditTime: 2024-02-04 16:19:00
 */
import { ikStore, ikTree, paramType, passwordEncry } from 'iking-utils'
import { ElMessage } from 'element-plus'
import router from '@g/router/index'
import api from '@g/api'
import type { ApiModel } from '@g/types/global'
import { userApi } from '@main/apis/user'
import { menuApi } from '@main/apis/menu'
import { loginApi } from '@main/apis/login'
import { ELoginType } from '@main/views/login/login-type'
import { tenantApi } from '@main/apis/tenant'
import { systemConfig } from '../../../system.config'
import useSocketStore from './socket'
import useSettingsStore from './settings'
import useMenuStore from './menu'
import useRouteStore from './route'
import useTabbarStore from './tabbar'

const { remberRoute } = systemConfig

const useUserStore = defineStore(
  // 唯一ID
  'user',
  () => {
    const tabbarStore = useTabbarStore()
    const routeStore = useRouteStore()
    const menuStore = useMenuStore()
    const settingStore = useSettingsStore()
    const socketStore = useSocketStore()

    const account = ref(ikStore.local.getItem(ELocal.ACCOUNT) ?? '')
    const token = ref(ikStore.local.getItem(ELocal.TOKEN) ?? '')
    const failure_time = ref(ikStore.local.getItem(ELocal.FAILURE_TIME) ?? '')
    const permissions = ref<string[]>([])
    const userInfo = ref(ikStore.local.getItem(ELocal.USER_INFO) ?? '')
    const pwdVisible = ref(Boolean(Number(ikStore.local.getItem(ELocal.PWD_VISIBLE) || 0)))
    const pwdType = ref('timeout')
    const settingId = ref(ikStore.local.getItem(ELocal.SETTING_ID) ?? '')
    const tenant = ref(ikStore.local.getItem(ELocal.TENANT) ?? '')
    const showTenant = ref(false)

    const organiza = ref(ikStore.local.getItem(ELocal.ORGANIZA) || {
      select: '',
      list: []
    })

    watch(
      () => settingStore.settings,
      (val: any) => {
        const sett = {
          userId: userInfo.value.id,
          configInfoList: [
            {
              value: JSON.stringify(val),
              type: 'THEME'
            },
            {
              type: 'LANGUAGE',
              value: val?.app?.defaultLang === 'zh-cn' ? 'zh-CN' : 'en-US'
            }
          ]
        }
        settingId.value && ((sett as any).id = settingId.value)
        setUserSetting(sett as any)
      },
      { deep: true }
    )

    const isLogin = computed(() => {
      let retn = false
      if (token.value) {
        // 如果前端需要判断token过期时间，则放开以下代码
        // if (new Date().getTime() < parseInt(failure_time.value) * 60 * 1000)
        if (tenant.value)
          retn = true
      }
      return retn
    })

    const handleLoginRes = async (res: { msg: string; data: any;success: boolean; }, type: string) => {
      const { msg, data, success } = res
      if (!success) {
        ElMessage.warning(msg)
        return
      }
      if (success) {
        // 系统右上角用户名
        account.value = data.name
        token.value = data.token
        failure_time.value = data.expire
      }
      updatePwdVisible(data?.passwordExpired || false)
      if (success && type === ELoginType.密码登录) {
        await ikStore.local.setItem(ELocal.TOKEN, data.token)
        ikStore.local.setItem(ELocal.ACCOUNT, data.name)
        ikStore.local.setItem(
          ELocal.FAILURE_TIME,
          new Date().getTime() + parseInt(data.expire || 99999) * 1000 * 60
        )
        ElMessage.success(msg)
      }
      loginApi.getPageCssFilter().then((res: any) => {
        ikStore.local.setItem(ELocal.GRRY, res?.data ?? 1)
      })
      // 获取用户详细信息userInfo
      await getUserInfo(data.id)
      // userInfo.value = data
      // ikStore.local.setItem(ELocal.USER_INFO, data)
      return res
    }

    const buildTokenAutoLoginRes = (token: string | undefined) => {
      return {
        code: 200,
        success: true,
        msg: '登录成功',
        pages: 0,
        total: 0,
        data: {
          name: '',
          token,
          expire: 0
        }
      }
    }

    const userTenant = async (params: any) => {
      // await tenantApi.addUserTenant(params)
    }
    const getLoginUser = async () => {
      await tenantApi.getLoginUser()
    }

    const queryAllDic = async () => {
      try {
        await getUserSetting()
        await getAllDiction()
      }
      catch (error) {
        console.info('error', error)
      }
    }

    const autoLoginNext = async () => {
      const res = await queryTenant()
      const tenantList = ref<any>(null)
      if (res?.success) {
        tenantList.value = res?.data || null
        if (res?.data?.length === 1) {
          if (res?.data[0].normal) {
            ikStore.local.setItem(ELocal.TENANT, res.data[0])
            tenant.value = res?.data[0]
            await userTenant(res?.data[0]?.code)
            await getLoginUser()
            await queryAllDic()
            if (!showTenant.value) {
              // router.push(redirect.value)
              return
            }
          }
          else {
            showTenant.value = true
          }
        }
        if (res?.data?.tenantList?.length > 1) {
          const loginTenant = res?.data?.tenantList.find(
            (item: any) => item.recent === true
          )
          if (loginTenant) {
            tenant.value = loginTenant
            ikStore.local.setItem(ELocal.TENANT, loginTenant)
            await userTenant(loginTenant?.code)
            await getLoginUser()
            await queryAllDic()
            if (!showTenant.value) {
              // router.push(redirect.value)
              return
            }
          }
        }
        showTenant.value = true
      }
      else {
        // res?.msg && msgError(res?.msg)
        showTenant.value = false
      }
    }
    async function autoLogin(token: string, to: any) {
      const res = await login({ token }, ELoginType.Token自动登录)
      await autoLoginNext()
      if (res?.success)
        router.push(to.path)
    }
    // 登录
    async function login(
      param: {
        account?: string
        password?: string
        phone?: string
        captcha?: string
        token?: string
      },
      type: string
    ) {
      let res: ApiModel = {
        msg: '',
        data: null,
        code: 0,
        pages: 0,
        success: false,
        total: 0
      }
      switch (type) {
        case ELoginType.Token自动登录:
          res = buildTokenAutoLoginRes(param.token)
          break
        case ELoginType.密码登录:
          res = await loginApi.login(
            {
              credentialName: param.account,
              password: passwordEncry(
                param.password || '',
                '1234567890000000',
                {
                  encode: 'hex'
                }
              ).AES.encrypt()
            },
            {
              headers: {
                'X-PASSWORD-ENCRYPT': 'encrypt'
              }
            }
          )
          break
        case ELoginType.短信登录:
          // 短信登录参数
          res = await loginApi.login(
            {
              phone: param.phone,
              smsVerifyCode: param.captcha
            },
            {
              headers: {
                'X-PASSWORD-ENCRYPT': 'encrypt'
              }
            }
          )
          break
        case ELoginType.微信登录:
          // 微信登录参数
          res = await loginApi.login(
            {
              wechatMiniOpenId: ''
            },
            {}
          )
          break
        case ELoginType.钉钉登录:
          // 钉钉登录参数
          break
        default:
          break
      }
      return handleLoginRes(res, type)
    }
    //
    function clearCache() {
      try {
        routeStore.removeRoutes()
        // routeStore.isGenerate = false
        ikStore.local.removeItem('account')
        ikStore.local.removeItem('token')
        ikStore.local.removeItem('failure_time')
        ikStore.local.removeItem('user_info')
        ikStore.local.removeItem('tenant')
        account.value = ''
        token.value = ''
        failure_time.value = ''
        permissions.value = []
        tabbarStore.clean()
        menuStore.setActived(0)
      }
      catch (error) {
        console.info('error: ', error)
      }
    }
    // 登出
    async function logout() {
      const { success } = await loginApi.loginOut()
      if (success) {
        router.push({
          path: '/login',
          query: remberRoute
            ? {
                redirect:
              router.currentRoute.value.path !== '/login'
                ? router.currentRoute.value.fullPath
                : undefined
              }
            : {}
        })
      }
      clearCache()
    }
    // 获取用户租户信息
    async function queryTenant() {
      if (!token.value)
        return null
      const res = await tenantApi.queryTenantList()
      return res
    }
    // 获取用户信息 通过
    async function getUserInfo(id: string) {
      if (!token.value)
        return null
      const { success, data } = await loginApi.getUserInfo(id)
      if (success) {
        userInfo.value = data
        if (!account.value)
          account.value = data.name
        data && ikStore.local.setItem(ELocal.USER_INFO, data)
        organiza.value = {
          select: data.organizationIds?.[0] || '',
          list: data.organizations
        }
        ikStore.local.setItem(ELocal.ORGANIZA, organiza.value)
        try {
          socketStore.createSocket()
        }
        catch (error) {

        }
      }
    }

    // 获取字典
    async function getAllDiction() {
      const { success, msg, data } = await menuApi.getAllDiction()
      if (success) {
        const fa: Set<string> = new Set(
          data.map((item: { dictCode: string; }) => item?.dictCode)
        )
        for (const i of fa) data.push({ id: i, name: i })

        const dict: { [key: string]: any; } = {}
        const tree = ikTree.listToTree(data, { id: 'id', pid: 'dictCode' })
        for (const i of fa) dict[i] = tree.find(f => f.id === i)?.children
        ikStore.local.setItem(ELocal.DICTIONARY, dict)
      }
      else { ElMessage.warning(msg) }
    }

    // 获取我的权限
    async function getPermissions() {
      // 通过 mock 获取权限
      const res = await api.get('member/permission', {
        baseURL: '/mock/',
        params: {
          account: account.value
        }
      })
      permissions.value = res.data.permissions
      return permissions.value
    }
    // 修改密码
    async function editPassword(data: {
      password: string
      newpassword: string
    }) {
      await api.post(
        'member/edit/password',
        {
          account: account.value,
          password: data.password,
          newpassword: data.newpassword
        },
        {
          baseURL: '/mock/'
        }
      )
    }
    // 更新密码框状态
    function updatePwdVisible(bool: boolean, type = 'timeout') {
      pwdType.value = type
      pwdVisible.value = Boolean(bool)
      ikStore.local.setItem(ELocal.PWD_VISIBLE, bool ? 1 : 0)
    }
    // 获取并应用用户配置
    async function getUserSetting() {
      const { success, data, msg } = await userApi.getSetting()
      if (success && data?.configInfoList?.length) {
        const dataValue = data?.configInfoList?.find((item: any) => item.type === 'THEME')
        const sett = JSON.parse(dataValue?.value || '')
        if (!paramType.isObject(sett)) {
          console.warn('用户配置错误', sett)
          return
        }
        settingStore.updateSettings(sett)
        settingId.value = dataValue?.id
        ikStore.local.setItem(ELocal.SETTING, sett)
      }
      !success && console.warn(msg)
    }
    // 保存用户配置
    async function setUserSetting(config: {
      id?: string
      userId: string
      type: 'THEME' | 'LANGUAGE'
      value: string
    }) {
      const { success, msg } = await userApi.setSetting({
        ...config,
        global: false
      })
      !success && console.warn(msg)
      try {
        ikStore.local.setItem(ELocal.SETTING, JSON.parse((config as any)?.configInfoList?.find((item: any) => item.type === 'THEME')?.value || ''))
      }
      catch (error) {
      }
    }

    return {
      account,
      token,
      permissions,
      isLogin,
      userInfo,
      pwdVisible,
      pwdType,
      tenant,
      showTenant,
      organiza,
      login,
      autoLogin,
      logout,
      getPermissions,
      editPassword,
      updatePwdVisible,
      clearCache,
      getUserSetting,
      setUserSetting,
      queryTenant,
      getAllDiction,
      queryAllDic
    }
  }
)

export default useUserStore
